﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Hydra.Core
{
    internal class X64Scalpel : IScalpel
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private uint _pBaseAddr;

        [DllImport("core-x64")]
        private static extern int AceInject(int pid, bool wow64, uint pBaseAddr);
        [DllImport("kernel32")]
        private static extern int IsWow64Process(IntPtr handle, out bool wow64);

        public X64Scalpel()
        {
            InternalGetWow64BaseAddr();
        }

        private void InternalGetWow64BaseAddr()
        {
            using (var process = Process.Start("assist.exe"))
            {
                process.WaitForExit();
                _pBaseAddr = (uint)process.ExitCode;
                log.InfoFormat("Wow64 base addr is {0:X}", _pBaseAddr);
            }
        }

        public void Inject(int pid)
        {
            using (var process = Process.GetProcessById(pid))
            {
                bool wow64;
                if (IsWow64Process(process.Handle, out wow64) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                if (AceInject(pid, wow64, _pBaseAddr) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
        }
    }
}